package com.gemframework.common.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.gemframework.common.exception.ApiException;
import org.springframework.util.StringUtils;

import java.util.Date;


/**
 * TOKEN工具类
 * ClassName: JwtUtil
 * Description:
 * date: 2020/1/22 10:12
 *
 * @author afeng
 * @since JDK 1.8
 */
public class JwtUtil {

    /**
     * 获取请求头中key为“Authorization”的value == sessionId
     */
    public static final String AUTHORIZATION = "Authorization";
    /**
     * TOKEN规范 Bearer TOKEN
     */
    public static final String TOKEN_START = "Bearer";
    /**
     * token加密key
     */
    public static final String TOKEN_KEY = "userId";
    /**
     * token密钥
     */
    public static final String TOKEN_SECRET = "afeng2020";
    /**
     * token有效时间，单位毫秒
     */
    public static final long TOKEN_EXPIRE_TIME = 7 * 24 * 3600 * 1000;


    /**
     * 根据token获取用户id，如果不存在则抛出异常
     */
    public static String getUserId() {
        String token = getToken();
        String userId = queryByToken(token);
        if (StringUtils.isEmpty(userId)) {
            throw new ApiException("用户不存在");
        }
        return userId;
    }

    /**
     * 获取客户端TOKEN
     */
    public static String getToken() {
        try {
            String header = ServletUtils.getRequest().getHeader(AUTHORIZATION);
            if (StringUtils.hasText(header) && header.startsWith(TOKEN_START)) {
                return header.substring(7);//包括一个空格，所以7个字符
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 校验token是否正确
     *
     * @param value 加密的值
     * @param token 密钥
     * @return 是否正确
     */
    public static boolean verifyToken(String token, String value) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).withClaim(TOKEN_KEY, value).build();
            verifier.verify(token);
            return true;
        } catch (TokenExpiredException e) {
            //TOKEN过期
        } catch (Exception e) {
            //解密失败
        }
        return false;
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @param token token
     * @return token中包含的信息
     */
    public static String queryByToken(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(TOKEN_KEY).asString();
        } catch (JWTDecodeException e) {
            e.printStackTrace();
            //解密失败
        }
        return null;
    }

    /**
     * 生成签名
     *
     * @param value 需要加密的值
     * @return 加密的token
     */
    public static String createToken(String value) {
        try {
            Date date = new Date(System.currentTimeMillis() + TOKEN_EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            // 附带加密信息
            return JWT.create().withClaim(TOKEN_KEY, value).withExpiresAt(date).sign(algorithm);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
